package com.zengdada.authority.utils.where;

import com.alibaba.fastjson.JSONObject;
import com.zengdada.authority.utils.CommonUtils;
import com.zengdada.authority.utils.PublicSearchRangeAssist;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Map;

/**
 * @author zsa
 * @date 2020/9/10 16:34
 * @description TODO 是有问题的 多级情况下
 */
public class ExampleWhere extends Where {

    private Example example;
    private List<String> columns;
    private Map<String, String> fieldNames;
    private Example.Criteria criteria;
    private Formula prentFormula;

    public ExampleWhere() {
    }

    public ExampleWhere init(Example example, List<String> columns, Map<String, String> fieldNames) {
        this.example = example;
        this.columns = columns;
        this.fieldNames = fieldNames;
        return this;
    }

    public void init(Example example, List<String> columns, Map<String, String> fieldNames, Example.Criteria criteria, Formula prentFormula) {
        this.example = example;
        this.columns = columns;
        this.fieldNames = fieldNames;
        this.criteria = criteria;
        this.prentFormula = prentFormula;
    }

    public void setExample(Example example) {
        this.example = example;
    }

    public void setColumns(List<String> columns) {
        this.columns = columns;
    }

    public void setFieldNames(Map<String, String> fieldNames) {
        this.fieldNames = fieldNames;
    }

    public Example.Criteria analysis() {

        if (!isValid()) {
            return null;
        }

        if (example == null || columns == null || fieldNames == null) {
            throw new RuntimeException("ExampleWhere example,columns,fieldNames 必须初始化");
        }
        if (isRel()) {
//            List<String> extraFilters = new ArrayList<>(1);
//            List<String> anyWhereExtraFilters = new ArrayList<>(1);
            if (prentFormula == null) {
                criteria = example.createCriteria();
            } else if (prentFormula == Formula.AND) {
                criteria = example.and();
            } else {
                criteria = example.or();
            }
            for (Where param : getParams()) {
                if(param == null) {
                    continue;
                }
                ExampleWhere dmlWhere = JSONObject.parseObject(JSONObject.toJSONString(param), ExampleWhere.class);
                dmlWhere.init(example, columns, fieldNames, criteria, getFormulaE());
                dmlWhere.analysis();
            }
        } else {
            if (prentFormula == null) {
                criteria = example.createCriteria();
            }
            if (columns.contains(getField().toUpperCase())) {
                setField(fieldNames.get(getField().toUpperCase()));
            } else if (columns.contains(CommonUtils.humpToLine(getField()).toUpperCase())) {
                setField(fieldNames.get(CommonUtils.humpToLine(getField()).toUpperCase()));
            } else {
                return null;
            }
            switch (getFormulaE()) {
                case GREATER:
                    if (prentFormula == Formula.AND) {
                        criteria.andGreaterThan(getField(), getCriteriaConditionVal());
                    } else {
                        criteria.orGreaterThan(getField(), getCriteriaConditionVal());
                    }
                    break;
                case LESS:
                    if (prentFormula == Formula.AND) {
                        criteria.andLessThan(getField(), getCriteriaConditionVal());
                    } else {
                        criteria.orLessThan(getField(), getCriteriaConditionVal());
                    }
                    break;
                case NOT_EQUAL:
                    if (prentFormula == Formula.AND) {
                        criteria.andNotEqualTo(getField(), getCriteriaConditionVal());
                    } else {
                        criteria.orNotEqualTo(getField(), getCriteriaConditionVal());
                    }
                    break;
                case LIKE:
                    if (prentFormula == Formula.AND) {
                        criteria.andLike(getField(), "%" + getCriteriaConditionVal() + "%");
                    } else {
                        criteria.orLike(getField(), "%" + getCriteriaConditionVal() + "%");
                    }
                    break;
                case END:
                case START:
                    if (prentFormula == Formula.AND) {
                        criteria.andCondition(String.format("%s LIKE ", getField()), getCriteriaConditionVal());
                    } else {
                        criteria.orCondition(String.format("%s LIKE ", getField()), getCriteriaConditionVal());
                    }
                    break;
                case IN:
                    List conditionVal = (List) getCriteriaConditionVal();
                    if (conditionVal.size() > 0) {
                        if (prentFormula == Formula.AND) {
                            criteria.andIn(getField(), conditionVal);
                        } else {
                            criteria.orIn(getField(), conditionVal);
                        }
                    } else {
                        if (prentFormula == Formula.AND) {
                            criteria.andCondition("1 = 2");
                        } else {
                            criteria.orCondition("1 = 2");
                        }
                    }
                    break;
                case NOT_IN:
                    List conditionVal1 = (List) getCriteriaConditionVal();
                    if (conditionVal1.size() > 0) {
                        if (prentFormula == Formula.AND) {
                            criteria.andNotIn(getField(), conditionVal1);
                        } else {
                            criteria.orNotIn(getField(), conditionVal1);
                        }
                    } else {
                        if (prentFormula == Formula.AND) {
                            criteria.andCondition("1 = 2");
                        } else {
                            criteria.orCondition("1 = 2");
                        }
                    }
                    break;
                case IS_NULL:
                    if (prentFormula == Formula.AND) {
                        criteria.andIsNull(getField());
                    } else {
                        criteria.orIsNull(getField());
                    }
                    break;
                case IS_NOT_NULL:
                    if (prentFormula == Formula.AND) {
                        criteria.andIsNotNull(getField());
                    } else {
                        criteria.orIsNotNull(getField());
                    }
                    break;
                case RANGE:
                    PublicSearchRangeAssist range = (PublicSearchRangeAssist) getCriteriaConditionVal();
//                    criteria.andCondition(String.format("BETWEEN %s", search.getField()), range.getFront());
//                    criteria.andCondition(String.format("%s", search.getField()), range.getAfter());
                    if (prentFormula == Formula.AND) {
                        criteria.andBetween(getField(), range.getFront(), range.getAfter());
                    } else {
                        criteria.orBetween(getField(), range.getFront(), range.getAfter());
                    }
                    break;
                default:
                    if (prentFormula == Formula.AND) {
                        criteria.andEqualTo(getField(), getCriteriaConditionVal());
                    } else {
                        criteria.orEqualTo(getField(), getCriteriaConditionVal());
                    }
            }
            return criteria;
        }
        return null;
    }
}
